%%writefile lab/vector_add.cpp
//==============================================================
// Copyright © Intel Corporation
//
// SPDX-License-Identifier: MIT
// =============================================================
#include <sycl/sycl.hpp>

using namespace sycl;

int main() {
    const int N = 256;
    
    //# Initialize a vector and print values
    std::vector<int> vector1(N, 10);
    std::cout<<"\nInput Vector1: ";    
    for (int i = 0; i < N; i++) std::cout << vector1[i] << " ";

    //# STEP 1 : Create second vector, initialize to 20 and print values

    //# YOUR CODE GOES HERE
    std::vector<int> vector2(N, 20);
    std::cout<<"\nInput Vector2: ";    
    for (int i = 0; i < N; i++) std::cout << vector2[i] << " ";
    
    
    
    //# Create Buffer
    
    buffer vector1_buffer(vector1);

    //# STEP 2 : Create buffer for second vector 

    //# YOUR CODE GOES HERE
    buffer vector2_buffer(vector2);



    //# Submit task to add vector
    queue q;
    q.submit([&](handler &h) {
      //# Create accessor for vector1_buffer
      accessor vector1_accessor (vector1_buffer,h);
      
      //# STEP 3 - add second accessor for second buffer

      //# YOUR CODE GOES HERE
       accessor vector2_accessor (vector2_buffer, h, read_only);



      h.parallel_for(range<1>(N), [=](id<1> index) {

        //# STEP 4 : Modify the code below to add the second vector to first one
        
        vector1_accessor[index] += vector2_accessor[index];
        

      });
   });

 
  //# Create a host accessor to copy data from device to host
  host_accessor h_a(vector1_buffer,read_only);

  //# Print Output values 
  std::cout<<"\nOutput Values: ";
  for (int i = 0; i < N; i++) std::cout<< vector1[i] << " ";
  std::cout<<"\n";

  return 0;
}







%%writefile lab/usm_lab.cpp
//==============================================================
// Copyright © Intel Corporation
//
// SPDX-License-Identifier: MIT
// =============================================================
#include <sycl/sycl.hpp>
#include <cmath>
using namespace sycl;

static const int N = 1024;

int main() {
  queue q;
  std::cout << "Device : " << q.get_device().get_info<info::device::name>() << "\n";

  //intialize 2 arrays on host
  int *data1 = static_cast<int *>(malloc(N * sizeof(int)));
  int *data2 = static_cast<int *>(malloc(N * sizeof(int)));
  for (int i = 0; i < N; i++) {
    data1[i] = 25;
    data2[i] = 49;
  }
    
  //# STEP 1 : Create USM device allocation for data1 and data2

  //# YOUR CODE GOES HERE

  int *device_data1 = malloc_device<int>(N, q);
  int *device_data2 = malloc_device<int>(N, q);



    
  //# STEP 2 : Copy data1 and data2 to USM device allocation
    
  //# YOUR CODE GOES HERE  

  q.memcpy(device_data1, data1, N * sizeof(int)).wait();
  q.memcpy(device_data2, data2, N * sizeof(int)).wait();



  //# STEP 3 : Write kernel code to update data1 on device with sqrt of value

  q.parallel_for(N, [=](auto i) { 

    //# YOUR CODE GOES HERE 
      
  });



  //# STEP 3 : Write kernel code to update data2 on device with sqrt of value
    
  q.parallel_for(N, [=](auto i) { 

    //# YOUR CODE GOES HERE 
      
  });


  //# STEP 5 : Write kernel code to add data2 on device to data1
    
  q.parallel_for(N, [=](auto i) { 

  //# YOUR CODE GOES HERE 
      
  });



  //# STEP 6 : Copy data1 on device to host
    
  //# YOUR CODE GOES HERE 
  q.memcpy(data1, device_data1, N * sizeof(int)).wait();






  //# verify results
  int fail = 0;
  for (int i = 0; i < N; i++) if(data1[i] != 12) {fail = 1; break;}
  if(fail == 1) std::cout << " FAIL"; else std::cout << " PASS";
  std::cout << "\n";


  //# STEP 7 : Free USM device allocations

  //# YOUR CODE GOES HERE
  free(device_data1, q);
  free(device_data2, q);



  //# STEP 8 : Add event based kernel dependency for the Steps 2 - 6
  free(data1);
  free(data2);

  return 0;
}